/*
 *    Copyright 2014-2017 Alexey Danilov
 *    Copyright 2021 Institute of Software Chinese Academy of Sciences, ISRC

 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.danikula.videocache.interfacers;

import com.danikula.videocache.ProxyCacheException;
import com.danikula.videocache.file.DiskUsage;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

import static com.danikula.videocache.Constants.TEMP_POSTFIX;

/**
 * Cache for proxy.
 *
 * @author Alexey Danilov (danikula@gmail.com).
 */
public abstract class Cache {
    /**
     * 当前读写的碎片文件
     */
    public File file;
    /**
     * 随机流操作的文件
     */
    protected RandomAccessFile dataFile;
    /**
     * 缓存文件夹剩余空间检测工具
     */
    protected DiskUsage diskUsage;

    /**
     * 单文件多节点读取缓存数据 (仅读缓存的时候)
     *
     * @param buffer 读取byte数组
     * @param offset 读取起点
     * @param length 读取长度
     * @return 读取的数据
     * @throws ProxyCacheException 读取错误信息
     */
    public abstract int read(byte[] buffer, long offset, int length) throws ProxyCacheException;

    /**
     * 当前缓存文件的缓存长度
     *
     * @return 当前缓存文件的缓存长度
     * @throws ProxyCacheException 代理缓存错误
     */
    public abstract long available() throws ProxyCacheException;

    /**
     * 缓存流程结束 关闭文件流 检测以及更新缓存区文件信息
     *
     * @throws ProxyCacheException 代理缓存错误
     */
    public synchronized void close() throws ProxyCacheException {
        try {
            dataFile.close();
            diskUsage.touch(file);
        } catch (IOException e) {
            throw new ProxyCacheException("Error closing file " + file, e);
        }
    }

    /**
     * 缓存完成之后的操作(重命名临时文件 重新设置随机文件操作对象)
     *
     * @throws ProxyCacheException 代理缓存错误
     */
    public abstract void complete() throws ProxyCacheException;

    /**
     * 视频数据是否缓存完毕
     *
     * @return 是否缓存完毕
     * @throws ProxyCacheException 代理缓存错误
     */
    public abstract boolean isCompleted() throws ProxyCacheException;

    /**
     * 是否是临时文件
     *
     * @param file 随机流当前操作的文件
     * @return 是否是临时文件
     */
    public boolean isTempFile(File file) {
        return file.getName().endsWith(TEMP_POSTFIX);
    }

    /**
     * 缓存完毕之后将临时文件重命名
     *
     * @throws ProxyCacheException 代理缓存错误
     */
    protected void renameFile() throws ProxyCacheException {
        close();
        String fileName = file.getName().substring(0, file.getName().length() - TEMP_POSTFIX.length());
        File completedFile = new File(file.getParentFile(), fileName);
        boolean renamed = file.renameTo(completedFile);
        if (!renamed) {
            throw new ProxyCacheException("Error renaming file " + file + " to " + completedFile + " for completion!");
        }
        file = completedFile;
        try {
            dataFile = new RandomAccessFile(file, "r");
            diskUsage.touch(file);
        } catch (IOException e) {
            throw new ProxyCacheException("Error opening " + file + " as disc cache", e);
        }
    }
}
